package com.hcl.orm.core.spring;

import com.hcl.orm.core.exception.ExceptionUtil;
import com.hcl.orm.core.executor.DaoMethodExecutor;
import org.springframework.jdbc.core.JdbcOperations;

import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * @author hucl
 * @projectName jim-orm
 * @description: TODO
 * @date 2021/5/1218:20
 */
public class MultiDialectDaoInvocationHandler<T> implements InvocationHandler, Serializable {
    private final JdbcOperations jdbcOperations;
    private Map<Method, DaoMethodExecutor> methodCache;

    public MultiDialectDaoInvocationHandler(final JdbcOperations jdbcOperations,
                                            Map<Method, DaoMethodExecutor> methodCache) {
        this.jdbcOperations = jdbcOperations;
        this.methodCache = methodCache;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (Object.class.equals(method.getDeclaringClass())) {
            try {
                return method.invoke(this, args);
            } catch (Throwable t) {
                throw ExceptionUtil.unwrapThrowable(t);
            }
        }
        final DaoMethodExecutor mapperMethod = cachedDaoMethod(method);
        return mapperMethod.execute(jdbcOperations, args);
    }

    private DaoMethodExecutor cachedDaoMethod(Method method) {
        DaoMethodExecutor daoMethodExecutor = methodCache.get(method);
        if (daoMethodExecutor == null) {
            daoMethodExecutor = new DaoMethodExecutor(method);
            methodCache.put(method, daoMethodExecutor);
        }
        return daoMethodExecutor;
    }
}
